#ifndef     __DE_MUX_H
#define     __DE_MUX_H

extern "C" {
#include <libavformat/avformat.h>
}
#include "../utils/error.h"
#include "../../utils/nocopyable.h"
#include "../utils/packet.h"

class DeMux : private utils::NoCopyable {

public:
    DeMux(const QString &file_path) {
        auto fp = file_path.toLatin1();
        int ec = avformat_open_input(
            &m_ctx,
            fp.constData(),
            nullptr,
            nullptr
        );
        if (ec < 0) {
            throw FFmpegException("avformat_open_input", ec);
        }

        ec = avformat_find_stream_info(m_ctx, nullptr);
        if (ec < 0) {
            avformat_close_input(&m_ctx);
            throw FFmpegException("avformat_find_stream_info", ec);
        }

        m_video_index = av_find_best_stream(
            m_ctx,
            AVMEDIA_TYPE_VIDEO,
            -1, -1,
            nullptr,
            0
        );
        if (m_video_index < 0) {
            avformat_close_input(&m_ctx);
            throw FFmpegException("av_find_best_stream video index", m_video_index);
        }

        m_audio_index = av_find_best_stream(
            m_ctx,
            AVMEDIA_TYPE_AUDIO,
            -1, -1,
            nullptr,
            0
        );
        if (m_audio_index < 0) {
            avformat_close_input(&m_ctx);
            throw FFmpegException("av_find_best_stream audio index", m_video_index);
        }
    }

    ~DeMux() {
        avformat_close_input(&m_ctx);
    }

    bool read_packet(AVPacket *pkt) {
        return av_read_frame(m_ctx, pkt) >= 0;
    }

    int video_index() const { return m_video_index; }
    int audio_index() const { return m_audio_index; }

    AVStream* video_stream() {
        return m_ctx->streams[m_video_index];
    }
    AVStream* audio_stream() {
        return m_ctx->streams[m_audio_index];
    }

private:
    AVFormatContext *m_ctx = nullptr;
    int m_video_index;
    int m_audio_index;
};


#endif
